"""
数据访问服务

提供统一的数据访问接口和业务逻辑。
"""

from typing import List, Optional, Dict, Any
from datetime import datetime
import logging

from src.core.di import Injectable, Inject, Service
from src.repositories import VideoRepository, TaskRepository, ProjectRepository
from src.models import Video, VideoMetadata, VideoClassification, ProcessingTask, Project
from src.models.task import TaskStatus, TaskType


@Service("data_service")
class DataService:
    """
    数据访问服务
    
    提供统一的数据访问接口，封装仓库操作和业务逻辑。
    """
    
    def __init__(self,
                 video_repo: VideoRepository = Inject(VideoRepository),
                 task_repo: TaskRepository = Inject(TaskRepository),
                 project_repo: ProjectRepository = Inject(ProjectRepository),
                 logger: logging.Logger = Inject("logger")):
        self.video_repo = video_repo
        self.task_repo = task_repo
        self.project_repo = project_repo
        self.logger = logger
    
    # ==================== 视频相关操作 ====================
    
    async def create_video_record(self, video_data: Dict[str, Any]) -> Video:
        """创建视频记录"""
        try:
            video = self.video_repo.create_from_dict(video_data)
            self.logger.info(f"创建视频记录: {video.file_name} (ID: {video.id})")
            return video
        except Exception as e:
            self.logger.error(f"创建视频记录失败: {e}")
            raise
    
    async def get_video_with_details(self, video_id: int) -> Optional[Video]:
        """获取包含所有详细信息的视频"""
        return self.video_repo.get_with_all_relations(video_id)
    
    async def find_videos_by_criteria(self, 
                                    category: str = None,
                                    format: str = None,
                                    min_duration: float = None,
                                    max_duration: float = None,
                                    processed_only: bool = None) -> List[Video]:
        """根据条件查找视频"""
        videos = []
        
        # 根据分类查找
        if category:
            videos = self.video_repo.find_by_category(category)
        else:
            videos = self.video_repo.get_all()
        
        # 应用其他过滤条件
        if format:
            videos = [v for v in videos if v.format == format]
        
        if min_duration is not None:
            videos = [v for v in videos if v.duration and v.duration >= min_duration]
        
        if max_duration is not None:
            videos = [v for v in videos if v.duration and v.duration <= max_duration]
        
        if processed_only is not None:
            videos = [v for v in videos if v.is_processed == processed_only]
        
        return videos
    
    async def update_video_processing_status(self, video_id: int, is_processed: bool) -> bool:
        """更新视频处理状态"""
        try:
            success = self.video_repo.mark_as_processed(video_id) if is_processed else True
            if success:
                self.logger.info(f"更新视频处理状态: ID={video_id}, processed={is_processed}")
            return success
        except Exception as e:
            self.logger.error(f"更新视频处理状态失败: {e}")
            return False
    
    async def get_video_statistics(self) -> Dict[str, Any]:
        """获取视频统计信息"""
        try:
            stats = {
                'processing_stats': self.video_repo.get_processing_statistics(),
                'format_stats': self.video_repo.get_statistics_by_format(),
                'resolution_stats': self.video_repo.get_statistics_by_resolution(),
                'category_stats': self.video_repo.get_statistics_by_category()
            }
            return stats
        except Exception as e:
            self.logger.error(f"获取视频统计信息失败: {e}")
            return {}
    
    # ==================== 任务相关操作 ====================
    
    async def create_processing_task(self, task_data: Dict[str, Any]) -> ProcessingTask:
        """创建处理任务"""
        try:
            task = self.task_repo.create_from_dict(task_data)
            self.logger.info(f"创建处理任务: {task.task_name} (ID: {task.id})")
            return task
        except Exception as e:
            self.logger.error(f"创建处理任务失败: {e}")
            raise
    
    async def get_next_task(self, worker_id: str, task_types: List[TaskType] = None) -> Optional[ProcessingTask]:
        """获取下一个待处理任务"""
        try:
            task = self.task_repo.get_next_pending_task(task_types)
            if task:
                # 开始任务
                task.start(worker_id)
                self.task_repo.update_from_dict(task.id, task.to_dict())
                self.logger.info(f"分配任务给工作节点: {task.task_name} -> {worker_id}")
            return task
        except Exception as e:
            self.logger.error(f"获取下一个任务失败: {e}")
            return None
    
    async def update_task_progress(self, task_id: int, progress: float, message: str = None) -> bool:
        """更新任务进度"""
        try:
            task = self.task_repo.get_by_id(task_id)
            if task:
                task.update_progress(progress, message)
                self.task_repo.update_from_dict(task_id, task.to_dict())
                return True
            return False
        except Exception as e:
            self.logger.error(f"更新任务进度失败: {e}")
            return False
    
    async def complete_task(self, task_id: int, output_data: Dict[str, Any] = None) -> bool:
        """完成任务"""
        try:
            task = self.task_repo.get_by_id(task_id)
            if task:
                task.complete(output_data)
                self.task_repo.update_from_dict(task_id, task.to_dict())
                self.logger.info(f"任务完成: {task.task_name}")
                return True
            return False
        except Exception as e:
            self.logger.error(f"完成任务失败: {e}")
            return False
    
    async def fail_task(self, task_id: int, error_message: str, error_details: Dict[str, Any] = None) -> bool:
        """任务失败"""
        try:
            task = self.task_repo.get_by_id(task_id)
            if task:
                task.fail(error_message, error_details)
                self.task_repo.update_from_dict(task_id, task.to_dict())
                self.logger.warning(f"任务失败: {task.task_name} - {error_message}")
                return True
            return False
        except Exception as e:
            self.logger.error(f"标记任务失败失败: {e}")
            return False
    
    async def get_task_queue_status(self) -> Dict[str, Any]:
        """获取任务队列状态"""
        try:
            queue_status = self.task_repo.get_queue_status()
            performance_stats = self.task_repo.get_performance_statistics()
            worker_stats = self.task_repo.get_worker_statistics()
            
            return {
                'queue_status': queue_status,
                'performance_statistics': performance_stats,
                'worker_statistics': worker_stats
            }
        except Exception as e:
            self.logger.error(f"获取任务队列状态失败: {e}")
            return {}
    
    async def cleanup_old_tasks(self, days: int = 30) -> int:
        """清理旧任务"""
        try:
            cleaned_count = self.task_repo.cleanup_old_tasks(days)
            self.logger.info(f"清理了 {cleaned_count} 个旧任务")
            return cleaned_count
        except Exception as e:
            self.logger.error(f"清理旧任务失败: {e}")
            return 0
    
    # ==================== 项目相关操作 ====================
    
    async def create_project(self, project_data: Dict[str, Any]) -> Project:
        """创建项目"""
        try:
            project = self.project_repo.create_from_dict(project_data)
            self.logger.info(f"创建项目: {project.name} (ID: {project.id})")
            return project
        except Exception as e:
            self.logger.error(f"创建项目失败: {e}")
            raise
    
    async def add_videos_to_project(self, project_id: int, video_ids: List[int]) -> Dict[str, Any]:
        """批量添加视频到项目"""
        try:
            added_count = 0
            failed_count = 0
            
            for video_id in video_ids:
                try:
                    if self.project_repo.add_video_to_project(project_id, video_id):
                        added_count += 1
                    else:
                        failed_count += 1
                except Exception:
                    failed_count += 1
            
            self.logger.info(f"添加视频到项目: 成功 {added_count}, 失败 {failed_count}")
            
            return {
                'added_count': added_count,
                'failed_count': failed_count,
                'total_requested': len(video_ids)
            }
        except Exception as e:
            self.logger.error(f"批量添加视频到项目失败: {e}")
            return {'added_count': 0, 'failed_count': len(video_ids), 'total_requested': len(video_ids)}
    
    async def get_project_with_videos(self, project_id: int) -> Optional[Project]:
        """获取包含视频的项目"""
        return self.project_repo.get_with_videos(project_id)
    
    async def get_project_detailed_stats(self, project_id: int) -> Dict[str, Any]:
        """获取项目详细统计"""
        try:
            return self.project_repo.get_project_statistics(project_id)
        except Exception as e:
            self.logger.error(f"获取项目统计失败: {e}")
            return {}
    
    async def duplicate_project(self, project_id: int, new_name: str) -> Optional[Project]:
        """复制项目"""
        try:
            new_project = self.project_repo.duplicate_project(project_id, new_name)
            if new_project:
                self.logger.info(f"复制项目: {new_name} (ID: {new_project.id})")
            return new_project
        except Exception as e:
            self.logger.error(f"复制项目失败: {e}")
            return None
    
    # ==================== 综合查询和分析 ====================
    
    async def get_dashboard_data(self) -> Dict[str, Any]:
        """获取仪表板数据"""
        try:
            # 视频统计
            video_stats = await self.get_video_statistics()
            
            # 任务统计
            task_stats = await self.get_task_queue_status()
            
            # 项目统计
            project_stats = self.project_repo.get_global_statistics()
            
            # 最近活动
            recent_videos = self.video_repo.find_recent(days=7)
            recent_tasks = self.task_repo.find_recent(days=7)
            recent_projects = self.project_repo.find_recent(days=7)
            
            return {
                'video_statistics': video_stats,
                'task_statistics': task_stats,
                'project_statistics': project_stats,
                'recent_activity': {
                    'videos': [v.to_dict() for v in recent_videos[:10]],
                    'tasks': [t.to_dict() for t in recent_tasks[:10]],
                    'projects': [p.to_dict() for p in recent_projects[:10]]
                }
            }
        except Exception as e:
            self.logger.error(f"获取仪表板数据失败: {e}")
            return {}
    
    async def search_content(self, keyword: str, content_types: List[str] = None) -> Dict[str, Any]:
        """全局内容搜索"""
        try:
            results = {}
            
            if not content_types or 'videos' in content_types:
                results['videos'] = self.video_repo.search_by_filename(keyword)
            
            if not content_types or 'projects' in content_types:
                results['projects'] = self.project_repo.search_by_name(keyword)
            
            return results
        except Exception as e:
            self.logger.error(f"内容搜索失败: {e}")
            return {}
    
    async def get_system_health(self) -> Dict[str, Any]:
        """获取系统健康状态"""
        try:
            # 检查各种指标
            health_status = {
                'database_status': 'healthy',
                'video_processing': {
                    'total_videos': self.video_repo.count(),
                    'unprocessed_videos': len(self.video_repo.find_unprocessed()),
                    'unavailable_videos': len(self.video_repo.find_unavailable())
                },
                'task_processing': {
                    'pending_tasks': len(self.task_repo.find_pending()),
                    'running_tasks': len(self.task_repo.find_running()),
                    'failed_tasks': len(self.task_repo.find_failed()),
                    'stuck_tasks': len(self.task_repo.find_stuck_tasks())
                },
                'storage': {
                    'total_projects': self.project_repo.count(),
                    'active_projects': len(self.project_repo.find_active())
                }
            }
            
            # 判断整体健康状态
            if (health_status['task_processing']['stuck_tasks'] > 0 or
                health_status['video_processing']['unavailable_videos'] > 10):
                health_status['overall_status'] = 'warning'
            else:
                health_status['overall_status'] = 'healthy'
            
            return health_status
        except Exception as e:
            self.logger.error(f"获取系统健康状态失败: {e}")
            return {'overall_status': 'error', 'error': str(e)}
    
    async def perform_maintenance(self) -> Dict[str, Any]:
        """执行系统维护"""
        try:
            maintenance_results = {}
            
            # 清理孤立数据
            maintenance_results['orphaned_metadata_cleaned'] = self.video_repo.cleanup_orphaned_metadata()
            maintenance_results['orphaned_classifications_cleaned'] = self.video_repo.cleanup_orphaned_classifications()
            
            # 清理旧任务
            maintenance_results['old_tasks_cleaned'] = self.task_repo.cleanup_old_tasks(30)
            
            # 取消卡住的任务
            maintenance_results['stuck_tasks_cancelled'] = self.task_repo.cancel_stuck_tasks(2)
            
            # 清理空项目
            maintenance_results['empty_projects_cleaned'] = self.project_repo.cleanup_empty_projects()
            
            self.logger.info(f"系统维护完成: {maintenance_results}")
            return maintenance_results
        except Exception as e:
            self.logger.error(f"系统维护失败: {e}")
            return {'error': str(e)}
